{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PS Clock Control\n",
    "This notebook demonstrates how to use `Clocks` class to control the PL clocks.\n",
    "\n",
    "By default, there are at most 4 PL clocks enabled in the system. They all can be reprogrammed to valid clock rates.\n",
    "\n",
    "Whenever the overlay is downloaded, the required clocks will also be configured.\n",
    "\n",
    "References:\n",
    "\n",
    "https://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import os, warnings\n",
    "from pynq import PL\n",
    "from pynq import Overlay\n",
    "\n",
    "if not os.path.exists(PL.bitfile_name):\n",
    "    warnings.warn('There is no overlay loaded after boot.', UserWarning)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note**: If you see a warning message in the above cell, it means that no overlay\n",
    "has been loaded after boot, hence the PL server is not aware of the \n",
    "current status of the PL. In that case you won't be able to run this notebook\n",
    "until you manually load an overlay at least once using:\n",
    "\n",
    "```python\n",
    "from pynq import Overlay\n",
    "ol = Overlay('your_overlay.bit')\n",
    "```\n",
    "\n",
    "If you do not see any warning message, you can safely proceed.\n",
    "\n",
    "### Show All Clocks\n",
    "\n",
    "The following example shows all the current clock rates on the board. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU:   650.000000MHz\n",
      "FCLK0: 100.000000MHz\n",
      "FCLK1: 142.857143MHz\n",
      "FCLK2: 200.000000MHz\n",
      "FCLK3: 100.000000MHz\n"
     ]
    }
   ],
   "source": [
    "from pynq import Clocks\n",
    "\n",
    "print(f'CPU:   {Clocks.cpu_mhz:.6f}MHz')\n",
    "print(f'FCLK0: {Clocks.fclk0_mhz:.6f}MHz')\n",
    "print(f'FCLK1: {Clocks.fclk1_mhz:.6f}MHz')\n",
    "print(f'FCLK2: {Clocks.fclk2_mhz:.6f}MHz')\n",
    "print(f'FCLK3: {Clocks.fclk3_mhz:.6f}MHz')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set Clock Rates\n",
    "The easiest way is to set the attributes directly. Random clock rates are used in the following examples; the clock manager will set the clock rates with best effort.\n",
    "\n",
    "If the desired frequency and the closest possible clock rate differs more than 1%, a warning will be raised."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU:   650.000000MHz\n",
      "FCLK0: 27.027027MHz\n",
      "FCLK1: 31.250000MHz\n",
      "FCLK2: 14.492754MHz\n",
      "FCLK3: 0.251953MHz\n"
     ]
    }
   ],
   "source": [
    "Clocks.fclk0_mhz = 27.123456\n",
    "Clocks.fclk1_mhz = 31.436546\n",
    "Clocks.fclk2_mhz = 14.597643\n",
    "Clocks.fclk3_mhz = 0.251954\n",
    "\n",
    "print(f'CPU:   {Clocks.cpu_mhz:.6f}MHz')\n",
    "print(f'FCLK0: {Clocks.fclk0_mhz:.6f}MHz')\n",
    "print(f'FCLK1: {Clocks.fclk1_mhz:.6f}MHz')\n",
    "print(f'FCLK2: {Clocks.fclk2_mhz:.6f}MHz')\n",
    "print(f'FCLK3: {Clocks.fclk3_mhz:.6f}MHz')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reset Clock Rates\n",
    "Recover the original clock rates. This can be done by simply reloading the overlay\n",
    "(overlay will be downloaded automatically after instantiation)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FCLK0: 100.000000MHz\n",
      "FCLK1: 142.857143MHz\n",
      "FCLK2: 200.000000MHz\n",
      "FCLK3: 100.000000MHz\n"
     ]
    }
   ],
   "source": [
    "_ = Overlay(PL.bitfile_name)\n",
    "\n",
    "print(f'FCLK0: {Clocks.fclk0_mhz:.6f}MHz')\n",
    "print(f'FCLK1: {Clocks.fclk1_mhz:.6f}MHz')\n",
    "print(f'FCLK2: {Clocks.fclk2_mhz:.6f}MHz')\n",
    "print(f'FCLK3: {Clocks.fclk3_mhz:.6f}MHz')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
